package com.ingenieria.industrial.dao.implementacion;

import com.ingenieria.industrial.dao.diseño.IUsuarioDAO;
import com.ingenieria.industrial.dto.Usuario;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

public class UsuarioDAO extends BaseDAO implements IUsuarioDAO {

    private Connection cn = null;
    private PreparedStatement ps = null;
    private ResultSet rs = null;
    private String sqlQuery = null;

    public UsuarioDAO(Connection cnx) {
        super(cnx);
    }

    @Override
    public boolean insert(Usuario usuario) throws SQLException {
        sqlQuery = "INSERT INTO t_usuarios(cod_usu, nombre, clave, cod_rol, estado) VALUES(?, ?, ?, ?, ?)";
        int pos = 1;
        try {
            cn = ConexionDB.getConnection();
            cn.setAutoCommit(false);
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(pos++, usuario.getCod_usu());
            ps.setString(pos++, usuario.getNombre());
            ps.setString(pos++, usuario.getClave());
            ps.setString(pos++, "R002");
            ps.setString(pos++, "A");
            if (ps.executeUpdate() == 0) {
                throw new SQLException("No se pudo registrar al usuario");
            }
            cn.commit();
            return true;
        } catch (SQLException e) {
            cn.rollback();
            throw new SQLException(e.getMessage());
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                throw new SQLException(e.getMessage());
            }
        }
    }

    @Override
    public boolean insertInfAdic(Usuario usuario) throws SQLException {
        sqlQuery = "INSERT INTO t_personas(dni,ape_pat,ape_mat,nombres,celular,mail,faceb,twitter,pag_web) VALUES(?,?,?,?,?,?,?,?,?)";
        String sql1 = "INSERT INTO t_inf_aca(dni,niv_aca,est_post,prod_aca,prod_aca_descrip,cert_aca,are_int_cal,"
                + " are_int_fin,are_int_log,are_int_man,are_int_mark,are_int_oper,are_int_proy,are_int_resp_soc,"
                + " are_int_tal_hum,are_int_otr) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
        String sql2 = "INSERT INTO t_inf_pro(dni,tra_act,area,cargo,periodo,exp_lab,are_int_lab_cal,are_int_lab_fin, "
                + " are_int_lab_log,are_int_lab_man,are_int_lab_mark,are_int_lab_oper,are_int_lab_proy,are_int_lab_resp_soc, "
                + " are_int_lab_tal_hum,are_lab_int_otr) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
        int pos = 1;
        int pos1 = 1;
        int pos2 = 1;
        try {
            cn = ConexionDB.getConnection();
            cn.setAutoCommit(false);
            //Guardando info personal
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(pos++, usuario.getDni());
            ps.setString(pos++, usuario.getApe_pat());
            ps.setString(pos++, usuario.getApe_mat());
            ps.setString(pos++, usuario.getNombres());
            ps.setString(pos++, usuario.getCelular());
            ps.setString(pos++, usuario.getMail());
            ps.setString(pos++, usuario.getFaceb());
            ps.setString(pos++, usuario.getTwitter());
            ps.setString(pos++, usuario.getPag_web());

            //Guardando info académica
            PreparedStatement ps1 = cn.prepareStatement(sql1);
            ps1.setString(pos1++, usuario.getDniAca());
            ps1.setString(pos1++, usuario.getNiv_aca());
            ps1.setString(pos1++, usuario.getEst_post());
            ps1.setString(pos1++, usuario.getProd_aca());
            ps1.setString(pos1++, usuario.getProd_aca_descrip());
            ps1.setString(pos1++, usuario.getCert_aca());
            ps1.setString(pos1++, usuario.getAre_int_cal());
            ps1.setString(pos1++, usuario.getAre_int_fin());
            ps1.setString(pos1++, usuario.getAre_int_log());
            ps1.setString(pos1++, usuario.getAre_int_man());
            ps1.setString(pos1++, usuario.getAre_int_mark());
            ps1.setString(pos1++, usuario.getAre_int_oper());
            ps1.setString(pos1++, usuario.getAre_int_proy());
            ps1.setString(pos1++, usuario.getAre_int_resp_soc());
            ps1.setString(pos1++, usuario.getAre_int_tal_hum());
            ps1.setString(pos1++, usuario.getAre_int_otr());

            //Guardando info profesional
            PreparedStatement ps2 = cn.prepareCall(sql2);
            ps2.setString(pos2++, usuario.getDniPro());
            ps2.setString(pos2++, usuario.getTra_act());
            ps2.setString(pos2++, usuario.getArea());
            ps2.setString(pos2++, usuario.getCargo());
            ps2.setString(pos2++, usuario.getPeriodo());
            ps2.setString(pos2++, usuario.getExp_lab());
            ps2.setString(pos2++, usuario.getAre_int_lab_cal());
            ps2.setString(pos2++, usuario.getAre_int_lab_fin());
            ps2.setString(pos2++, usuario.getAre_int_lab_log());
            ps2.setString(pos2++, usuario.getAre_int_lab_man());
            ps2.setString(pos2++, usuario.getAre_int_lab_mark());
            ps2.setString(pos2++, usuario.getAre_int_lab_oper());
            ps2.setString(pos2++, usuario.getAre_int_lab_proy());
            ps2.setString(pos2++, usuario.getAre_int_lab_resp_soc());
            ps2.setString(pos2++, usuario.getAre_int_lab_tal_hum());
            ps2.setString(pos2++, usuario.getAre_lab_int_otr());

            if (ps.executeUpdate() == 0) {
                throw new SQLException("No se pudo registrar los datos");
            }
            if (ps1.executeUpdate() == 0) {
                throw new SQLException("No se pudo registrar los datos");
            }
            if (ps2.executeUpdate() == 0) {
                throw new SQLException("No se pudo registrar los datos");
            }
            cn.commit();
            return true;
        } catch (SQLException e) {
            cn.rollback();
            throw new SQLException(e.getMessage());
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                throw new SQLException(e.getMessage());
            }
        }
    }

    @Override
    public boolean update(Usuario usuario) throws SQLException {
        sqlQuery = "UPDATE t_usuarios SET "
                + " nombre = ? "
                + " WHERE cod_usu = ?";
        try {
            int pos = 1;
            cn = ConexionDB.getConnection();
            cn.setAutoCommit(false);
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(pos++, usuario.getNombre());
            ps.setString(pos++, usuario.getCod_usu());
            if (ps.executeUpdate() == 0) {
                throw new SQLException("No se pudo modificar los datos");
            }
            cn.commit();
            return true;
        } catch (SQLException e) {
            cn.rollback();
            throw new SQLException(e.getMessage());
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                throw new SQLException(e.getMessage());
            }
        }
    }

    @Override
    public boolean updateInfAdic(Usuario usuario) throws SQLException {
        sqlQuery = "UPDATE t_personas SET "
                + " ape_pat = ?, ape_mat = ?, nombres = ?, celular = ?, mail = ?, "
                + " faceb = ?, twitter = ?, pag_web = ? "
                + " WHERE dni = ?";
        String sql1 = "UPDATE t_inf_aca SET "
                + " niv_aca = ?, est_post = ?, prod_aca = ?, prod_aca_descrip = ?, "
                + " cert_aca = ?, are_int_cal = ?, are_int_fin = ?, are_int_log = ?,are_int_man= ?, are_int_mark = ?, "
                + " are_int_oper= ?, are_int_proy = ?, are_int_resp_soc = ?, are_int_tal_hum = ?, are_int_otr = ? "
                + " WHERE idAca = ?";
        String sql2 = "UPDATE t_inf_pro SET "
                + " tra_act = ?, area = ?, cargo = ?, periodo = ?, exp_lab = ?, are_int_lab_cal = ?, are_int_lab_fin = ?, "
                + " are_int_lab_log = ?, are_int_lab_man = ?, are_int_lab_mark = ?, are_int_lab_oper = ?, are_int_lab_proy = ?,"
                + " are_int_lab_resp_soc = ?, are_int_lab_tal_hum = ?, are_lab_int_otr = ? "
                + " WHERE idPro = ?";
        int pos = 1;
        int pos1 = 1;
        int pos2 = 1;
        try {
            cn = ConexionDB.getConnection();
            cn.setAutoCommit(false);

            //Modificando info personal
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(pos++, usuario.getApe_pat());
            ps.setString(pos++, usuario.getApe_mat());
            ps.setString(pos++, usuario.getNombres());
            ps.setString(pos++, usuario.getCelular());
            ps.setString(pos++, usuario.getMail());
            ps.setString(pos++, usuario.getFaceb());
            ps.setString(pos++, usuario.getTwitter());
            ps.setString(pos++, usuario.getPag_web());
            ps.setString(pos++, usuario.getDni());

            //Modificando info académica
            PreparedStatement ps1 = cn.prepareStatement(sql1);
            ps1.setString(pos1++, usuario.getNiv_aca());
            ps1.setString(pos1++, usuario.getEst_post());
            ps1.setString(pos1++, usuario.getProd_aca());
            ps1.setString(pos1++, usuario.getProd_aca_descrip());
            ps1.setString(pos1++, usuario.getCert_aca());
            ps1.setString(pos1++, usuario.getAre_int_cal());
            ps1.setString(pos1++, usuario.getAre_int_fin());
            ps1.setString(pos1++, usuario.getAre_int_log());
            ps1.setString(pos1++, usuario.getAre_int_man());
            ps1.setString(pos1++, usuario.getAre_int_mark());
            ps1.setString(pos1++, usuario.getAre_int_oper());
            ps1.setString(pos1++, usuario.getAre_int_proy());
            ps1.setString(pos1++, usuario.getAre_int_resp_soc());
            ps1.setString(pos1++, usuario.getAre_int_tal_hum());
            ps1.setString(pos1++, usuario.getAre_int_otr());
            ps1.setInt(pos1++, usuario.getIdAca());

            //Modificando info profesional
            PreparedStatement ps2 = cn.prepareStatement(sql2);
            ps2.setString(pos2++, usuario.getTra_act());
            ps2.setString(pos2++, usuario.getArea());
            ps2.setString(pos2++, usuario.getCargo());
            ps2.setString(pos2++, usuario.getPeriodo());
            ps2.setString(pos2++, usuario.getExp_lab());
            ps2.setString(pos2++, usuario.getAre_int_lab_cal());
            ps2.setString(pos2++, usuario.getAre_int_lab_fin());
            ps2.setString(pos2++, usuario.getAre_int_lab_log());
            ps2.setString(pos2++, usuario.getAre_int_lab_man());
            ps2.setString(pos2++, usuario.getAre_int_lab_mark());
            ps2.setString(pos2++, usuario.getAre_int_lab_oper());
            ps2.setString(pos2++, usuario.getAre_int_lab_proy());
            ps2.setString(pos2++, usuario.getAre_int_lab_resp_soc());
            ps2.setString(pos2++, usuario.getAre_int_lab_tal_hum());
            ps2.setString(pos2++, usuario.getAre_lab_int_otr());
            ps2.setInt(pos2++, usuario.getIdPro());

            if (ps.executeUpdate() == 0) {
                throw new SQLException("No se pudo modificar los datos");
            }
            if (ps1.executeUpdate() == 0) {
                throw new SQLException("No se pudo modificar los datos");
            }
            if (ps2.executeUpdate() == 0) {
                throw new SQLException("No se pudo modificar los datos");
            }

            cn.commit();
            return true;
        } catch (SQLException e) {
            cn.rollback();
            throw new SQLException(e.getMessage());
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                throw new SQLException(e.getMessage());
            }
        }
    }

    @Override
    public boolean delete(String cod_usu) {
        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    }

    @Override
    public ArrayList<Usuario> getAll() {
        ArrayList<Usuario> lista = null;
        Usuario usuario = null;
        sqlQuery = "SELECT u.*, r.* FROM t_usuarios u "
                + " INNER JOIN t_roles r on u.cod_rol = r.cod_rol ORDER BY u.nombre";
        try {
            cn = ConexionDB.getConnection();
            ps = cn.prepareStatement(sqlQuery);
            rs = ps.executeQuery();
            lista = new ArrayList<>();
            while (rs.next()) {
                usuario = new Usuario();
                mapearBeanForRS(rs, usuario);
                lista.add(usuario);
            }
        } catch (SQLException e) {
            lista = null;
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
            }
        }
        return lista;
    }

    @Override
    public Usuario getById(String cod_usu) {
        Usuario usuario = null;
        sqlQuery = "SELECT u.*, r.descrip FROM t_usuarios u "
                + " INNER JOIN t_roles r ON u.cod_rol = r.cod_rol "
                + " WHERE u.cod_usu = ?";
        try {
            cn = ConexionDB.getConnection();
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(1, cod_usu);
            rs = ps.executeQuery();
            while (rs.next()) {
                usuario = new Usuario();
                mapearBeanForRS(rs, usuario);
            }
        } catch (SQLException e) {
            usuario = null;
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
            }
        }
        return usuario;
    }

    @Override
    public Usuario login(String cod_usu, String clave) {
        Usuario usuario = null;
        cn = ConexionDB.getConnection();
        sqlQuery = "SELECT u.*, r.descrip as descrip_rol FROM t_usuarios u "
                + " INNER JOIN t_roles r ON u.cod_rol = r.cod_rol "
                + " WHERE u.clave = ? AND u.cod_usu = ?";
        if (cn != null) {
            try {
                ps = cn.prepareStatement(sqlQuery);
                ps.setString(1, clave);
                ps.setString(2, cod_usu);
                rs = ps.executeQuery();
                while (rs.next()) {
                    usuario = new Usuario();
                    mapearBeanForRS(rs, usuario);
                }
            } catch (SQLException e) {
                usuario = null;
            } finally {
                try {
                    if (cn != null) {
                        cn.close();
                    }
                    if (ps != null) {
                        ps.close();
                    }
                    if (rs != null) {
                        rs.close();
                    }
                } catch (SQLException ex) {
                }
            }
        }
        return usuario;
    }

    @Override
    public Usuario getInfPer(String cod_usu) throws SQLException {
        sqlQuery = "SELECT * FROM t_personas WHERE dni = ?";
        Usuario usuario = null;
        try {
            cn = ConexionDB.getConnection();
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(1, cod_usu);
            rs = ps.executeQuery();
            while (rs.next()) {
                usuario = new Usuario();
                mapearBeanForRS(rs, usuario);
            }
        } catch (SQLException e) {
            usuario = null;
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
            }
        }
        return usuario;
    }

    @Override
    public Usuario getInfAdic(String cod_usu) throws SQLException {
        sqlQuery = "SELECT u.*, p.*, infAca.idAca AS idAca, infAca.dni AS dniAca, infAca.niv_aca, infAca.est_post, "
                + " infAca.prod_aca, infAca.prod_aca_descrip, infAca.cert_aca, infAca.are_int_cal,infAca.are_int_fin,infAca.are_int_log, "
                + " infAca.are_int_man,infAca.are_int_mark,infAca.are_int_oper,infAca.are_int_proy,infAca.are_int_resp_soc, "
                + " infAca.are_int_tal_hum,infAca.are_int_otr, infPro.idPro AS idPro, infPro.dni AS dniPro, infPro.tra_act, "
                + " infPro.area, infPro.cargo, infPro.periodo, infPro.exp_lab, infPro.are_int_lab_cal, infPro.are_int_lab_fin, "
                + " infPro.are_int_lab_log,infPro.are_int_lab_man,infPro.are_int_lab_mark,infPro.are_int_lab_oper, "
                + " infPro.are_int_lab_proy,infPro.are_int_lab_resp_soc,infPro.are_int_lab_tal_hum,infPro.are_lab_int_otr "
                + " FROM t_usuarios u INNER JOIN t_personas p ON u.cod_usu = p.dni "
                + " INNER JOIN t_inf_aca infAca ON p.dni = infAca.dni "
                + " INNER JOIN t_inf_pro infPro ON infAca.dni = infPro.dni "
                + " WHERE u.cod_usu = ?";
        Usuario usuario = null;
        try {
            cn = ConexionDB.getConnection();
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(1, cod_usu);
            rs = ps.executeQuery();
            while (rs.next()) {
                usuario = new Usuario();
                mapearBeanForRS(rs, usuario);
            }
        } catch (SQLException e) {
            usuario = null;
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
            }
        }
        return usuario;
    }

    @Override
    public ArrayList<Usuario> getListaAlumnos() throws SQLException {
        ArrayList<Usuario> lista = null;
        Usuario usuario = null;
        sqlQuery = " SELECT concat_ws(' ', p.ape_pat,p.ape_mat,p.nombres) AS alumno, "
                + " p.mail, p.pag_web, u.*, i.* "
                + " FROM t_personas p "
                + " INNER JOIN t_inf_aca u ON p.dni = u.dni "
                + " INNER JOIN t_inf_pro i ON u.dni = i.dni "
                + " ORDER BY alumno ";
        try {
            cn = ConexionDB.getConnection();
            ps = cn.prepareStatement(sqlQuery);
            rs = ps.executeQuery();
            lista = new ArrayList<>();
            while (rs.next()) {
                usuario = new Usuario();
                mapearBeanForRS(rs, usuario);
                lista.add(usuario);
            }
        } catch (SQLException e) {
            lista = null;
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
            }
        }
        return lista;
    }

    @Override
    public Usuario getByEmail(String email) throws SQLException {
        sqlQuery = "SELECT * FROM t_personas WHERE mail = ?";
        Usuario usuario = null;
        try {
            cn = ConexionDB.getConnection();
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(1, email);
            rs = ps.executeQuery();
            while (rs.next()) {
                usuario = new Usuario();
                mapearBeanForRS(rs, usuario);
            }
        } catch (SQLException e) {
            usuario = null;
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
            }
        }
        return usuario;
    }

    @Override
    public boolean updPassByEmail(String pass, String cod_usu) throws SQLException {
        sqlQuery = "UPDATE t_usuarios SET "
                + " clave = ? "
                + " WHERE cod_usu = ?";
        try {
            int pos = 1;
            cn = ConexionDB.getConnection();
            cn.setAutoCommit(false);
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(pos++, pass);
            ps.setString(pos++, cod_usu);
            if (ps.executeUpdate() == 0) {
                throw new SQLException("No se pudo modificar los datos");
            }
            cn.commit();
            return true;
        } catch (SQLException e) {
            cn.rollback();
            throw new SQLException(e.getMessage());
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                throw new SQLException(e.getMessage());
            }
        }
    }

    @Override
    public Usuario getByPassActCodUsu(String passAct, String cod_usu) throws SQLException {
        sqlQuery = "SELECT * FROM t_usuarios WHERE clave = ? AND cod_usu = ?";
        Usuario usuario = null;
        try {
            cn = ConexionDB.getConnection();
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(1, passAct);
            ps.setString(2, cod_usu);
            rs = ps.executeQuery();
            while (rs.next()) {
                usuario = new Usuario();
                mapearBeanForRS(rs, usuario);
            }
        } catch (SQLException e) {
            usuario = null;
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
            }
        }
        return usuario;
    }

    @Override
    public boolean changePass(Usuario usuario) throws SQLException {
        sqlQuery = "UPDATE t_usuarios SET "
                + " clave = ? "
                + " WHERE cod_usu = ?";
        try {
            int pos = 1;
            cn = ConexionDB.getConnection();
            cn.setAutoCommit(false);
            ps = cn.prepareStatement(sqlQuery);
            ps.setString(pos++, usuario.getClave());
            ps.setString(pos++, usuario.getCod_usu());
            if (ps.executeUpdate() == 0) {
                throw new SQLException("No se pudo modificar los datos");
            }
            cn.commit();
            return true;
        } catch (SQLException e) {
            cn.rollback();
            throw new SQLException(e.getMessage());
        } finally {
            try {
                if (cn != null) {
                    cn.close();
                }
                if (ps != null) {
                    ps.close();
                }
                if (rs != null) {
                    rs.close();
                }
            } catch (SQLException e) {
                throw new SQLException(e.getMessage());
            }
        }
    }

}
